import time
import unittest
import xmlrpc.client
import multiprocessing

import app


class XMLRPCTest(unittest.TestCase):
    poll = None
    server_process = None

    @classmethod
    def setUpClass(cls):
        """ Sets up the XML-RPC server for testing in a separate process. """
        cls.server_process = multiprocessing.Process(target=app.app.run)
        cls.server_process.start()
        cls.poll = xmlrpc.client.ServerProxy('http://localhost:5000/v'+app.__MAJOR__)
        time.sleep(0.2)  # Give the Flask server some time to start before we connect. Increase if you get errors.

    @classmethod
    def tearDownClass(cls):
        cls.server_process.terminate()

    def test_get(self):
        """ We should be able to get data from the XML-RPC server. """
        i = 1  # poll_id
        self.assertEqual(self.poll.index(), str(i))
        self.assertEqual(self.poll.get_question(i), app.db[i].question)
        self.assertEqual(self.poll.get_options(i), '1 2 3')
        self.assertEqual(self.poll.get_option_description(i, 1), app.db[i].options[1].description)

    def test_fault(self):
        """ We should get a fault response if the poll id doesn't exist. """
        # self.assertRaises(xmlrpc.client.Fault, self.poll.get_question(0))
        # Unfortunately, flask_fastrpc doesn't return Fault responses per the XML-RPC specification:
        self.assertEqual(self.poll.get_question(0),
                         {'status': 500, 'statusMessage': '404 Not Found: Poll not found'})

    @unittest.skip("Functionality planned for version 2.1.x")
    def test_vote(self):
        """ We should be able to vote. """
        self.assertEqual(self.poll.result(1, 1, 'Alice'), 0)
        self.assertEqual(self.poll.vote(1, 1, 'Alice'), 'Ok')
        self.assertEqual(self.poll.result(1, 1, 'Alice'), 1)

    @unittest.skip("Functionality planned for version 2.1.x")
    def test_vote_double(self):
        """ We should not be able to vote twice. """
        self.assertEqual(self.poll.vote(1, 2, 'Eve'), 'Ok')
        self.assertNotEquals(self.poll.vote(1, 2, 'Eve'), 'Ok')
        self.assertNotEquals(self.poll.vote(1, 3, 'Eve'), 'Ok')

    @unittest.skip("Functionality planned for version 2.1.x")
    def test_vote_count(self):
        """ The vote count should be the same as the number of valid votes. """
        app.init_db() # Reset votes
        self.assertEqual(self.poll.vote(1, 2, 'Alice'), 'Ok')
        self.assertEqual(self.poll.vote(1, 2, 'Bob'), 'Ok')
        self.assertEqual(self.poll.vote(1, 3, 'Eve'), 'Ok')
        self.assertEqual(self.poll.result(1, 1), 0)
        self.assertEqual(self.poll.result(1, 2), 2)
        self.assertEqual(self.poll.result(1, 3), 1)


if __name__ == '__main__':
    unittest.main()

# Use python -m unittest discover app
